package com.maple.webrtc.socket

import android.util.Log
import com.blankj.utilcode.util.GsonUtils
import com.blankj.utilcode.util.NetworkUtils
import com.blankj.utilcode.util.PhoneUtils
import com.maple.webrtc.utils.LogUtils
import com.maple.webrtc.utils.ToastUtils
import io.ktor.client.HttpClient
import io.ktor.client.plugins.websocket.WebSockets
import io.ktor.client.plugins.websocket.webSocket
import io.ktor.http.HttpMethod
import io.ktor.websocket.DefaultWebSocketSession
import io.ktor.websocket.Frame
import io.ktor.websocket.close
import io.ktor.websocket.readText
import io.ktor.websocket.send
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.consumeEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.json.JSONObject


class Client(private val port: Int) {

    private var callback: Callback? = null

    fun setCallback(callback: Callback?) {
        this.callback = callback
    }

    private val client = HttpClient {
        install(WebSockets)
    }

    private var connectJob: Job? = null
    private var session: DefaultWebSocketSession? = null


    fun connect(host: String) {
        connectJob = CoroutineScope(Dispatchers.IO).launch {
            try {
                client.webSocket(method = HttpMethod.Get, host = host, port = port, path = "/socket") {
                    session = this
                    withContext(Dispatchers.Main) {
                        callback?.onConnected(host, port)
                    }
                    // 监听消息
                    incoming.consumeEach { frame ->
                        if (frame is Frame.Text) {
                            val receivedText = frame.readText()
                            withContext(Dispatchers.Main) {
                                callback?.onReceive(JSONObject(receivedText))
                            }
                        }
                    }
                }
            } catch (e: Exception) {
                LogUtils.logGGQ("Client connect ERROR：${e.message}")
            }
        }
    }

    fun close() {
        connectJob?.cancel()
        CoroutineScope(Dispatchers.IO).launch {
            try {
                session?.close()
            } catch (e: Exception) {
                LogUtils.logGGQ("Client close ERROR：${e.message}")
            }
        }
        client.close()
    }


    fun send(json: JSONObject) {
        CoroutineScope(Dispatchers.IO).launch {
            try {
                session?.send(json.toString())
            } catch (e: Exception) {
                LogUtils.logGGQ("Client send ERROR：${e.message}")
            }
        }
    }

    interface Callback {
        fun onConnected(host: String,port: Int)
        fun onReceive(json: JSONObject)
    }
}